home *** CD-ROM | disk | FTP | other *** search
/ Aminet 30 / Aminet 30 (1999)(Schatztruhe)[!][Apr 1999].iso / Aminet / dev / cross / GBDK-2.0.lha / GBDK / lib / rand.s < prev    next >
Text File  |  1998-10-01  |  4KB  |  118 lines

  1. ;/***************************************************************************
  2. ; *                                                                         *
  3. ; * Module  : rand.s                                                        *
  4. ; *                                                                         *
  5. ; * Purpose : A rand() generator using the linear congruential method       *
  6. ; *                                                                         *
  7. ; * Version : 1.01, January 7 1998                                          *
  8. ; *             Added _initrand to set seed without recompiling             *
  9. ; *           1, January 6 1998                                             *
  10. ; *                                                                         *
  11. ; * Author  : Luc Van den Borre ( Homepage : NOC.BASE.ORG )                 *
  12. ; *                                                                         *
  13. ; **************************************************************************/
  14.  
  15.     ;; Why use an algorithm for generating random numbers?
  16.     ;;
  17.     ;; - Given a certain seed value, the same sequence of random numbers is generated
  18.     ;;   every time. This is a good thing when debugging (reproducible). On the other
  19.     ;;   hand, you've got 2^16 seed values, each of which will produce a sequence of
  20.     ;;   numbers that stays different for any of the other sequences for 'an appreciable
  21.     ;;   time.' (I can't say how long exactly.)
  22.     ;;
  23.     ;; - The linear congruential method is one of the 'best' random number generators
  24.     ;;   around. However, this implementation uses a 16 bit accumulator, while at least
  25.     ;;   32 bits are needed for a generator that passes all the statistical tests.
  26.     ;;   Still, I'm relatively confident that this is random enough for even the most
  27.     ;;   demanding game.
  28.     ;;
  29.     ;;   Compare this to getting random values from one of the hardware registers
  30.     ;;   (not reproducible, might not have all values). An array might be the best bet
  31.     ;;   if you don't need a lot of values (or have lots of memory spare),
  32.     ;;   or if you want values to be within a certain range.
  33.     ;;   And both would be faster than this. Also, this definitely isn't the fastest
  34.     ;;   algorithm I know, and certainly for games less strict algorithms might be
  35.     ;;   appropriate (shift and xor ?).
  36.     ;;   It's your choice - but if you're doing Monte Carlo physics simulations on the
  37.     ;;   GameBoy, this is a safe bet!
  38.  
  39.     .include    "global.s"
  40.  
  41.     .area    _BSS
  42. .randhi::            ; Storage for last random number (or seed)
  43.     .ds    0x01
  44. .randlo::
  45.     .ds    0x01
  46.  
  47.     .area    _CODE
  48.  
  49.     ;; Random number generator using the linear congruential method
  50.     ;;  X(n+1) = (a*X(n)+c) mod m
  51.     ;; with a = 17, m = 16 and c = $5c93 (arbitrarily)
  52.     ;; The seed value is also chosen arbitrarily as $a27e
  53.     ;; Ref : D. E. Knuth, "The Art of Computer Programming" , Volume 2
  54.     ;;
  55.     ;; Exit conditions
  56.     ;;   DE = Random number [0,2^16-1]
  57.     ;;
  58.     ;; Registers used:
  59.     ;;   A, HL (need not be saved) and DE (return register)
  60.     ;;
  61.  
  62. _rand::
  63. _randw::
  64.     LD    A, (.randlo)
  65.     LD    L, A
  66.     LD    E, A        ; Save randlo
  67.     LD    A, (.randhi)
  68.     LD    D, A        ; Save randhi
  69.  
  70.     SLA    L        ; * 16
  71.     RLA
  72.     SLA    L
  73.     RLA
  74.     SLA    L
  75.     RLA
  76.     SLA    L
  77.     RLA
  78.     LD    H, A        ; Save randhi*16
  79.  
  80.     LD    A, E        ; Old randlo
  81.     ADD    A, L        ; Add randlo*16
  82.     LD    L, A        ; Save randlo*17
  83.  
  84.     LD    A, H        ; randhi*16
  85.     ADC    A, D        ; Add old randhi
  86.     LD    H, A        ; Save randhi*17
  87.  
  88.     LD    A, L        ; randlo*17
  89.     ADD    A, #0x93
  90.     LD    (.randlo), A
  91.     LD    D, A        ; Return register
  92.     LD    A, H        ; randhi*17
  93.     ADC    A, #0x5c
  94.     LD    (.randhi), A
  95.     LD    E, A        ; Return register
  96.  
  97.     ;; Note D is the low byte, E the high byte. This is intentional because
  98.     ;; the high byte can be slightly 'more random' than the low byte, and I presume
  99.     ;; most will cast the return value to a UBYTE. As if someone will use this, tha!
  100.     RET
  101.  
  102.     ;; This sets the seed value. Call it whenever you like
  103.     ;;
  104.     ;; Exit conditions
  105.     ;;   None
  106.     ;;
  107.     ;; Registers used:
  108.     ;;   A, HL (need not be saved) and DE (return register)
  109.     ;;
  110. _initrand::
  111.     LDA    HL,2(SP)
  112. .initrand::
  113.     LD    A, (HL+)
  114.     LD    (.randlo), A
  115.     LD    A, (HL)
  116.     LD    (.randhi), A
  117.     RET
  118.